上一章節 compiler 做的第一個步驟,就是語彙分析 ( lexing )。( 拆單字 )。
語彙分析會做的事:
語彙範疇 ( lexical scope ),就是在語彙分析時定義的範疇。就是寫 code 的人定義的範圍。
function foo(a) {
var b = a * 2;
function bar(c) {
console.log( a, b, c );
}
bar( b * 3);
}
foo( 2 ); // 2, 4, 12
這個範例程式碼有三個槽狀範疇 ( nested scopes )。
範疇泡泡 ( scope bubbles ) 的定義取決於那些範疇區塊 ( blocks of scope )。
這個章節先以函式做範疇的區分。
泡泡一定是包著泡泡,不會有一個泡泡被兩個獨立的泡泡分別包著。
依照前一個章節來拿東西,如果小倉庫沒位置拿,會到大倉庫拿,直到在全球總倉拿到東西。若沒有就報錯。
2
。a * 2
= 4
。b * 3
= 12
。但如果其實大小倉庫都有位置 a
,裡面放的東西不一樣。會拿什麼?
小倉庫的,這叫遮蔽 ( shadowing,內層識別字遮蔽了外層識別字 )。
但我還是想拿全球總倉的東西呢?
用 windows.a
。
這兩個技巧被唾棄,能不用就不用,但還是要了解一下。
如果你有條程式碼,想嵌在某個角落。就用 eval。
把這段程式碼寫成字串,就能放到 eval 裡面。
eval("var c = 1;") 等同於 var c = 1;
在全域環境呼叫的字串,就換傳進 function 內部,進而修改內部程式。
function foo(str, a){
eval( str ); // 作弊
console.log(a, b);
}
var b = 2;
foo( "var b = 3;", 1 ); // 1, 3
發生什麼事?
但在嚴格模式下,eval 不再起作用。
function foo(str){
"use strict";
eval( str );
console.log( a ); // ReferenceError
}
foo( "var a = 2;" );
其他能接受字串成為程式碼的函式
都是動態的修改程式碼內容。前兩個早被棄用,別這樣用。第三個建構子比較 eval 安全,但還是避免用。
因為用的機會少,還會降低效能喔!
已被棄用。之後再來了解棄用的原因。
(感覺是語法糖,但危害到身體健康)
當然會降低。
JavaScript 快速編譯,快速執行。中間會穿插著最佳化。
在 lexing 時期,遇到這兩個傢伙,就會先假設他們識別字是無效的(每個單字),因為你不知道為傳什麼進來。這樣怎麼進行最佳化?
就乾脆不進行了。少了最佳化,就會慢。